type GeometryType = 'Point'|'MultiPoint'|'Polygon'|'MultiPolygon'|'LineString'|'MultiLineString'
type Properties = Record<string, any>
type Points = Array<any>

type Options = {
    points: Points
    properties: Properties,
    type: GeometryType
}
import { Viewer, GroundPrimitive, PolygonGeometry, PolygonHierarchy, Cartesian3,GroundPolylineGeometry,Color, 
    GeometryInstance,ClassificationType,ColorGeometryInstanceAttribute,PerInstanceColorAppearance,CircleGeometry,
    GroundPolylinePrimitive,PolylineColorAppearance
} from 'cesium'
export default class Primitives {
    private len:number
    constructor(public options: Array<Options>) {
       this.len = this.options.length;
    }

    private createPolygonGeometry(points: Points) {
        const polygon = new PolygonGeometry({
            polygonHierarchy: new PolygonHierarchy(
                Cartesian3.fromDegreesArray(points)
            )
        })
        return polygon
    }

    private createPolylineGeometry(points: Points) {
        const polyline = new GroundPolylineGeometry({
            positions: Cartesian3.fromDegreesArray(points),
            width: 4
        })
        return polyline
    }

    private createCircleGeometry(points: Points) {
        const circle = new CircleGeometry({
            center: Cartesian3.fromDegrees(points[0], points[1]),
            radius: 2
        })
        return circle
    }

    private createGeometry(points:Points, type: GeometryType) {
        let geometry:PolygonGeometry|GroundPolylineGeometry|CircleGeometry|undefined = undefined
        switch (type) {
            case 'Point':
                geometry = this.createCircleGeometry(points)
                break;
            case 'MultiPoint': 
                geometry = this.createCircleGeometry(points)
                break;
            case 'LineString': 
                geometry = this.createPolylineGeometry(points);
                break;
            case 'MultiLineString': 
                geometry = this.createPolylineGeometry(points);
                break;
            case 'Polygon':
                geometry = this.createPolygonGeometry(points);
                break;
            case 'MultiPolygon': 
                geometry = this.createPolygonGeometry(points);
                break;
        } 
        return geometry;
    }

    public create(viewer: Viewer) {
        const geometryInstances = []
        while(this.len > 0) {
            let currentLen = this.len - 1
            const { points, properties, type} = this.options[currentLen]
            const geometry = this.createGeometry(points, type)
            if (!geometry) {
                continue;
            }
            geometryInstances.push(new GeometryInstance({
                geometry,
                attributes:{
                    color : ColorGeometryInstanceAttribute.fromColor(Color.fromRandom({alpha: 0.5}))
                }
            }))
            this.len --;
        } 
        let [lon, lat] = this.options[0].points
        viewer.camera.flyTo({
            destination: Cartesian3.fromDegrees(lon, lat, 50000)
        })
        if (geometryInstances[0].geometry instanceof GroundPolylineGeometry) {
            viewer.scene.groundPrimitives.add(new GroundPolylinePrimitive({
                geometryInstances,
                appearance : new PolylineColorAppearance()
            }))
        } else {
            viewer.scene.groundPrimitives.add(new GroundPrimitive({
                geometryInstances,
                classificationType: ClassificationType.TERRAIN,
                appearance: new PerInstanceColorAppearance()
            })) 
        }
    }
}